home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 1.iso / DEMON / RISCOS2 / TCP_131S.ARC / c / AX25SUBR < prev    next >
Text File  |  1992-03-17  |  13KB  |  424 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h> 
  4. #include <time.h>
  5. #include "global.h"
  6. #include "mbuf.h"
  7. #include "timer.h"
  8. #include "ax25.h"
  9. #include "lapb.h"
  10. #include <ctype.h>
  11.  
  12. static int16 ax25hash(struct ax25_addr *);
  13.  
  14. struct ax25_cb *ax25_cb[NHASH];
  15.  
  16. /* Default AX.25 parameters */
  17. int16 t1init = 10000 / MSPTICK; /* FRACK of 10 seconds */
  18. int16 t2init = 1000 / MSPTICK;  /* 1 sec acknowledgment delay */
  19. int16 t3init = 0 / MSPTICK;     /* No keep-alive polling */
  20. int16 t4init = 300000 / MSPTICK; /* 5 minutes of no I frame tx or rx => redundant link */
  21. int16 maxframe = 1;             /* Stop and wait */
  22. int16 n2 = 10;                  /* 10 retries */
  23. int16 axwindow = 2048;          /* 2K incoming text before RNR'ing */
  24. int16 paclen = 256;             /* 256-byte I fields */
  25. int16 pthresh = 128;            /* Send polls for packets larger than this */
  26.  
  27. /* Address hash function. Exclusive-ORs each byte, ignoring
  28.  * such insignificant, annoying things as E and H bits
  29.  */
  30. static int16 ax25hash(struct ax25_addr *s)
  31. {
  32.         register char x;
  33.         register int i;
  34.         register char *cp;
  35.  
  36.         x = 0;
  37.         cp = s->call;
  38.         for(i=ALEN; i!=0; i--)
  39.                 x ^= *cp++ & 0xfe;
  40.         x ^= s->ssid & SSID;
  41.         return uchar(x) % NHASH;
  42. }
  43. /* Look up entry in hash table */
  44. struct ax25_cb *find_ax25(register struct ax25_addr *addr)
  45. {
  46.         int16 hashval;
  47.         register struct ax25_cb *axp;
  48.  
  49.         /* Find appropriate hash chain */
  50.         hashval = ax25hash(addr);
  51.  
  52.         /* Search hash chain */
  53.         for(axp = ax25_cb[hashval]; axp != NULLAX25; axp = axp->next){
  54.                 if(addreq(&axp->addr.dest,addr)){
  55.                         return axp;
  56.                 }
  57.         }
  58.         return NULLAX25;
  59. }
  60.  
  61. /* Remove address entry from hash table */
  62. void del_ax25(register struct ax25_cb *axp)
  63. {
  64.         int16 hashval;
  65.  
  66.         if(axp == NULLAX25)
  67.                 return;
  68.         /* Remove from hash header list if first on chain */
  69.         hashval = ax25hash(&axp->addr.dest);
  70.  
  71.         /* Remove from chain list */
  72.         if(ax25_cb[hashval] == axp)
  73.                 ax25_cb[hashval] = axp->next;
  74.         if(axp->prev != NULLAX25)
  75.                 axp->prev->next = axp->next;
  76.         if(axp->next != NULLAX25)
  77.                 axp->next->prev = axp->prev;
  78.  
  79.         /* Timers should already be stopped, but just in case... */
  80.         stop_timer(&axp->t1);
  81.         stop_timer(&axp->t2);
  82.         stop_timer(&axp->t3);
  83.         stop_timer(&axp->t4);
  84.  
  85.         /* Free allocated resources */
  86.         free_q(&axp->txq);
  87.         free_q(&axp->rxasm);
  88.         free_q(&axp->rxq);
  89.         free((char *)axp);
  90.  
  91. }
  92.  
  93. /* Create an ax25 control block. Allocate a new structure, if necessary,
  94.  * and fill it with all the defaults. The caller
  95.  * is still responsible for filling in the reply address
  96.  */
  97. struct ax25_cb *cr_ax25(struct ax25_addr *addr)
  98. {
  99.         register struct ax25_cb *axp;
  100.         int16 hashval;
  101.  
  102.         if(addr == NULLAXADDR)
  103.                 return NULLAX25;
  104.  
  105.         if((axp = find_ax25(addr)) == NULLAX25){
  106.                 /* Not already in table; create an entry
  107.                  * and insert it at the head of the chain
  108.                  */
  109.                 /* Find appropriate hash chain */
  110.                 hashval = ax25hash(addr);
  111.                 axp = (struct ax25_cb *)calloc(1,sizeof(struct ax25_cb));
  112.                 if(axp == NULLAX25)
  113.                         return NULLAX25;
  114.                 /* Insert at beginning of chain */
  115.                 axp->prev = NULLAX25;
  116.                 axp->next = ax25_cb[hashval];
  117.                 if(axp->next != NULLAX25)
  118.                         axp->next->prev = axp;
  119.                 ax25_cb[hashval] = axp;
  120.         }
  121.         axp->maxframe = maxframe;
  122.         axp->window = axwindow;
  123.         axp->paclen = paclen;
  124.         axp->proto = V2;        /* Default, can be changed by other end */
  125.         axp->pthresh = pthresh;
  126.         axp->n2 = n2;
  127.         axp->t1.start = t1init;
  128.         axp->t1.func = recover;
  129.         axp->t1.arg = (char *)axp;
  130.  
  131.         axp->t2.start = t2init;
  132.         axp->t2.func = send_ack;
  133.         axp->t2.arg = (char *)axp;
  134.  
  135.         axp->t3.start = t3init;
  136.         axp->t3.func = pollthem;
  137.         axp->t3.arg = (char *)axp;
  138.  
  139.         axp->t4.start = t4init;
  140.         axp->t4.func = redundant;
  141.         axp->t4.arg = (char *)axp;
  142.  
  143.         axp->r_upcall = (void(*)())ax_incom;
  144.         return axp;
  145. }
  146.  
  147. /*
  148.  * setcall - convert callsign plus substation ID of the form
  149.  * "KA9Q-0" to AX.25 (shifted) address format
  150.  *   Address extension bit is left clear
  151.  *   Return -1 on error, 0 if OK
  152.  */
  153. int setcall(struct ax25_addr *out, char *call)
  154. {
  155.         int csize;
  156.         unsigned ssid;
  157.         register int i;
  158.         register char *cp,*dp;
  159.         char c;
  160.  
  161.         if(out == (struct ax25_addr *)NULL || call == NULLCHAR || *call == '\0'){
  162.                 return -1;
  163.         }
  164.         /* Find dash, if any, separating callsign from ssid
  165.          * Then compute length of callsign field and make sure
  166.          * it isn't excessive
  167.          */
  168.         dp = strchr(call,'-');
  169.         if(dp == NULLCHAR)
  170.                 csize = strlen(call);
  171.         else
  172.                 csize = dp - call;
  173.         if(csize > ALEN)
  174.                 return -1;
  175.         /* Now find and convert ssid, if any */
  176.         if(dp != NULLCHAR){
  177.                 dp++;   /* skip dash */
  178.                 ssid = atoi(dp);
  179.                 if(ssid > 15)
  180.                         return -1;
  181.         } else
  182.                 ssid = 0;
  183.         /* Copy upper-case callsign, left shifted one bit */
  184.         cp = out->call;
  185.         for(i=0;i<csize;i++){
  186.                 c = *call++;
  187.                 if(islower(c))
  188.                         c = toupper(c);
  189.                 *cp++ = c << 1;
  190.         }
  191.         /* Pad with shifted spaces if necessary */
  192.         for(;i<ALEN;i++)
  193.                 *cp++ = ' ' << 1;
  194.         
  195.         /* Insert substation ID field and set reserved bits */
  196.         out->ssid = 0x60 | (ssid << 1);
  197.         return 0;
  198. }
  199. /* Set a digipeater string in an ARP table entry */
  200. int setpath(char *out, char *in[], int cnt)
  201. {
  202.         struct ax25_addr addr;
  203.  
  204.         if(cnt == 0)
  205.                 return 0;
  206.         while(cnt-- != 0){
  207.                 setcall(&addr,*in++);
  208.                 addr.ssid &= ~E;
  209.                 out = putaxaddr(out,&addr);
  210.         }
  211.         out[-1] |= E;
  212.  
  213.         return 0;
  214. }
  215. int addreq(register struct ax25_addr *a, register struct ax25_addr *b)
  216. {
  217.         if(memcmp(a->call,b->call,ALEN) != 0)
  218.                 return 0;
  219.         if((a->ssid & SSID) != (b->ssid & SSID))
  220.                 return 0;
  221.         return 1;
  222. }
  223. /* Convert encoded AX.25 address to printable string */
  224. int pax25(char *e, struct ax25_addr *addr)
  225. {
  226.         register int i;
  227.         char c,*cp;
  228.  
  229.         cp = addr->call;
  230.         for(i=ALEN;i != 0;i--){
  231.                 c = (*cp++ >> 1) & 0x7f;
  232.                 if(c == ' ')
  233.                         break;
  234.                 *e++ = c;
  235.         }
  236.         if ((addr->ssid & SSID) != 0)
  237.                 sprintf(e,"-%d",(addr->ssid >> 1) & 0xf);       /* ssid */
  238.         else
  239.                 *e = 0;
  240.         return 0;
  241. }
  242. /* Print a string of AX.25 addresses in the form
  243.  * "KA9Q-0 [via N4HY-0,N2DSY-2]"
  244.  * Designed for use by ARP - arg is a char string
  245.  */
  246. int psax25(register char *e, register char *addr)
  247. {
  248.         int i;
  249.         struct ax25_addr axaddr;
  250.         char tmp[16];
  251.  
  252.         e[0] = '\0';    /* Give strcat a staritng point */
  253.         for(i=0;;i++){
  254.                 /* Create local copy in host-format structure */
  255.                 addr = getaxaddr(&axaddr,addr);
  256.  
  257.                 /* Create ASCII representation and append to output */
  258.                 pax25(tmp,&axaddr);
  259.                 strcat(e,tmp);
  260.  
  261.                 if(axaddr.ssid & E)
  262.                         break;
  263.                 if(i == 0)
  264.                         strcat(e," via ");
  265.                 else
  266.                         strcat(e,",");
  267.                 /* Not really necessary, but speeds up subsequent strcats */
  268.                 e += strlen(e);
  269.         }
  270.         return 0;
  271. }
  272. char *getaxaddr(register struct ax25_addr *ap, register char *cp)
  273. {
  274.         memcpy(ap->call,cp,ALEN);
  275.         cp += ALEN;
  276.         ap->ssid = *cp++;
  277.         return cp;
  278. }
  279. char *putaxaddr(register char *cp, register struct ax25_addr *ap)
  280. {
  281.         memcpy(cp,ap->call,ALEN);
  282.         cp += ALEN;
  283.         *cp++ = ap->ssid;
  284.         return cp;
  285. }
  286.  
  287. /* Convert a host-format AX.25 header into a mbuf ready for transmission */
  288. struct mbuf *htonax25(register struct ax25 *hdr, struct mbuf *data)
  289. {
  290.         struct mbuf *bp;
  291.         register char *cp;
  292.         register int16 i;
  293.  
  294.         if(hdr == (struct ax25 *)NULL || hdr->ndigis > MAXDIGIS)
  295.                 return NULLBUF;
  296.  
  297.         /* Allocate space for return buffer */
  298.         i = AXALEN * (2 + hdr->ndigis);
  299.         if((bp = pushdown(data,i)) == NULLBUF)
  300.                 return NULLBUF;
  301.  
  302.         /* Now convert */
  303.         cp = bp->data;
  304.  
  305.         hdr->dest.ssid &= ~E;   /* Dest E-bit is always off */
  306.         /* Encode command/response in C bits */
  307.         switch(hdr->cmdrsp){
  308.         case COMMAND:
  309.                 hdr->dest.ssid |= C;
  310.                 hdr->source.ssid &= ~C;
  311.                 break;
  312.         case RESPONSE:
  313.                 hdr->dest.ssid &= ~C;
  314.                 hdr->source.ssid |= C;
  315.                 break;
  316.         default:
  317.                 hdr->dest.ssid &= ~C;
  318.                 hdr->source.ssid &= ~C;
  319.                 break;
  320.         }
  321.         cp = putaxaddr(cp,&hdr->dest);
  322.  
  323.         /* Set E bit on source address if no digis */
  324.         if(hdr->ndigis == 0){
  325.                 hdr->source.ssid |= E;
  326.                 putaxaddr(cp,&hdr->source);
  327.                 return bp;
  328.         }
  329.         hdr->source.ssid &= ~E;
  330.         cp = putaxaddr(cp,&hdr->source);
  331.  
  332.         /* All but last digi get copied with E bit off */
  333.         for(i=0; i < hdr->ndigis - 1; i++){
  334.                 hdr->digis[i].ssid &= ~E;
  335.                 cp = putaxaddr(cp,&hdr->digis[i]);
  336.         }
  337.         hdr->digis[i].ssid |= E;
  338.         cp = putaxaddr(cp,&hdr->digis[i]);
  339.         return bp;
  340. }
  341. /* Convert an AX.25 ARP table entry into a host format address structure
  342.  * ready for use in transmitting a packet
  343.  */
  344. int atohax25(register struct ax25 *hdr, register char *hwaddr, 
  345.              struct ax25_addr *source)
  346. {
  347.         register struct ax25_addr *axp;
  348.  
  349.         hwaddr = getaxaddr(&hdr->dest,hwaddr);  /* Destination address */
  350.         hdr->source = *source;                  /* Source address */
  351.         if(hdr->dest.ssid & E){
  352.                 /* No digipeaters */
  353.                 hdr->ndigis = 0;
  354.                 hdr->dest.ssid &= ~E;
  355.                 hdr->source.ssid |= E;
  356.                 return 2;
  357.         }
  358.         hdr->source.ssid &= ~E;
  359.         hdr->dest.ssid &= ~E;
  360.         for(axp = hdr->digis; axp < &hdr->digis[MAXDIGIS]; axp++){
  361.                 hwaddr = getaxaddr(axp,hwaddr);
  362.                 if(axp->ssid & E){
  363.                         hdr->ndigis = axp - hdr->digis + 1;
  364.                         return hdr->ndigis;
  365.                 }
  366.         }
  367.         return -1;
  368. }
  369. /* Convert a network-format AX.25 header into a host format structure
  370.  * Return -1 if error, number of addresses if OK
  371.  */
  372. int ntohax25(register struct ax25 *hdr, struct mbuf **bpp)
  373. {
  374.         register struct ax25_addr *axp;
  375.         char buf[AXALEN];
  376.  
  377.         if(pullup(bpp,buf,AXALEN) < AXALEN)
  378.                 return -1;
  379.         getaxaddr(&hdr->dest,buf);
  380.  
  381.         if(pullup(bpp,buf,AXALEN) < AXALEN)
  382.                 return -1;
  383.         getaxaddr(&hdr->source,buf);
  384.  
  385.         /* Process C bits to get command/response indication */
  386.         if((hdr->source.ssid & C) == (hdr->dest.ssid & C))
  387.                 hdr->cmdrsp = UNKNOWN;
  388.         else if(hdr->source.ssid & C)
  389.                 hdr->cmdrsp = RESPONSE;
  390.         else
  391.                 hdr->cmdrsp = COMMAND;
  392.  
  393.         hdr->ndigis = 0;
  394.         if(hdr->source.ssid & E)
  395.                 return 2;       /* No digis */
  396.  
  397.         /* Process digipeaters */
  398.         for(axp = hdr->digis;axp < &hdr->digis[MAXDIGIS]; axp++){
  399.                 if(pullup(bpp,buf,AXALEN) < AXALEN)
  400.                         return -1;
  401.                 getaxaddr(axp,buf);
  402.                 if(axp->ssid & E){      /* Last one */
  403.                         hdr->ndigis = axp - hdr->digis + 1;
  404.                         return hdr->ndigis + 2;                 
  405.                 }
  406.         }
  407.         return -1;      /* Too many digis */
  408. }
  409.  
  410. /* Figure out the frame type from the control field
  411.  * This is done by masking out any sequence numbers and the
  412.  * poll/final bit after determining the general class (I/S/U) of the frame
  413.  */
  414. int16 ftype(register char control)
  415. {
  416.         if((control & 1) == 0)  /* An I-frame is an I-frame... */
  417.                 return uchar(I);
  418.         if(control & 2)         /* U-frames use all except P/F bit for type */
  419.                 return (uchar(control & ~PF));
  420.         else                    /* S-frames use low order 4 bits for type */
  421.                 return (uchar(control & 0xf));
  422. }
  423.  
  424.